// File Name: oled_ctrl.c
// Author: kukukukuku~
// Date: 2024-07-04

#include "./User/OLED/inc/oled_ctrl.h"

//设置界面选项对象
static OledMenuItem oledMenuItemOption[] = 
{
    {(uint8_t *)"Key", 1},
    {(uint8_t *)"LED", 1},
    {(uint8_t *)"OLED", 1},
    {(uint8_t *)"RS485", 1},
    {(uint8_t *)"Step motor", 1},
    {(uint8_t *)"WS2812B", 1},
    {(uint8_t *)"Save", 0},
    {(uint8_t *)"Reset", 0},
    {(uint8_t *)"<<<", 0},
};

//Key界面选项对象
static OledMenuItem oledMenuItemKey[] = 
{
    {(uint8_t *)"Click beep", 1},
    {(uint8_t *)"Long beep", 1},
    {(uint8_t *)"Lock", 0},
    {(uint8_t *)"<<<", 0},
};

//LED界面选项对象
static OledMenuItem oledMenuItemLed[] = 
{
    {(uint8_t *)"LED1", 1},
    {(uint8_t *)"LED2", 1},
    {(uint8_t *)"<<<", 0},
};

//LED设置界面选项对象
static OledMenuItem oledMenuItemLedOption[] = 
{
    {(uint8_t *)"Mode", 1},
    {(uint8_t *)"Breath step", 1},
    {(uint8_t *)"Blink freq", 1},
    {(uint8_t *)"On", 0},
    {(uint8_t *)"Off", 0},
    {(uint8_t *)"<<<", 0},
};

//LED模式界面选项对象
static OledMenuItem oledMenuItemLedMode[] = 
{
    {(uint8_t *)"Breath mode", 0},
    {(uint8_t *)"Blink mode", 0},
    {(uint8_t *)"Switch mode", 0},
    {(uint8_t *)"<<<", 0},
};

//OLED界面选项对象
static OledMenuItem oledMenuItemOled[] = 
{
    {(uint8_t *)"Off", 0},
    {(uint8_t *)"Dir", 1},
    {(uint8_t *)"Light", 1},
    {(uint8_t *)"Cursor style", 1},
    {(uint8_t *)"Refresh ms", 1},
    {(uint8_t *)"Menu number", 1},
    {(uint8_t *)"<<<", 0},
};

//OLED方向界面选项对象
static OledMenuItem oledMenuItemOledDir[] = 
{
    {(uint8_t *)"Normal", 0},
    {(uint8_t *)"Reverse", 0},
    {(uint8_t *)"<<<", 0},
};

//OLED亮度界面选项对象
static OledMenuItem oledMenuItemOledLight[] = 
{
    {(uint8_t *)"Light high", 0},
    {(uint8_t *)"Light mid", 0},
    {(uint8_t *)"Light low", 0},
    {(uint8_t *)"<<<", 0},
};

//OLED光标风格界面选项对象
static OledMenuItem oledMenuItemOledCursorStyle[] = 
{
    {(uint8_t *)"reverse", 0},
    {(uint8_t *)">", 0},
    {(uint8_t *)"*", 0},
    {(uint8_t *)"@", 0},
    {(uint8_t *)"->", 0},
    {(uint8_t *)"<-", 0},
    {(uint8_t *)"[ ]", 0},
    {(uint8_t *)"<<<", 0},
};

//OLED菜单编号界面选项对象
static OledMenuItem oledMenuItemOledMenuNumber[] = 
{
    {(uint8_t *)"show", 0},
    {(uint8_t *)"blank", 0},
    {(uint8_t *)"<<<", 0},
};

//RS485界面选项对象
static OledMenuItem oledMenuItemRs485[] = 
{
    {(uint8_t *)"Mode", 1},
    {(uint8_t *)"ID", 1},
    {(uint8_t *)"Baudrate", 1},
    {(uint8_t *)"Active ms", 1},
    {(uint8_t *)"<<<", 0},
};

//RS485模式界面选项对象
static OledMenuItem oledMenuItemRs485Mode[] = 
{
    {(uint8_t *)"Active mode", 0},
    {(uint8_t *)"Passive mode", 0},
    {(uint8_t *)"<<<", 0},
};

//RS485波特率界面选项对象
static OledMenuItem oledMenuItemRs485Baud[] = 
{
    {(uint8_t *)"9600", 0},
    {(uint8_t *)"19200", 0},
    {(uint8_t *)"38400", 0},
    {(uint8_t *)"57600", 0},
    {(uint8_t *)"74800", 0},
    {(uint8_t *)"115200", 0},
    {(uint8_t *)"230400", 0},
    {(uint8_t *)"460800", 0},
    {(uint8_t *)"500000", 0},
    {(uint8_t *)"576000", 0},
    {(uint8_t *)"<<<", 0},
};

//Step motor界面选项对象
static OledMenuItem oledMenuItemStepMotor[] = 
{
    {(uint8_t *)"Mode", 1},
    {(uint8_t *)"Speed", 1},
    {(uint8_t *)"<<<", 0},
};

//Step motor模式界面选项对象
static OledMenuItem oledMenuItemStepMotorMode[] = 
{
    {(uint8_t *)"FULL", 0},
    {(uint8_t *)"HALF", 0},
    {(uint8_t *)"QUARTER", 0},
    {(uint8_t *)"EIGHTH", 0},
    {(uint8_t *)"SIXTEENTH", 0},
    {(uint8_t *)"<<<", 0},
};

//Step motor转速界面选项对象
static OledMenuItem oledMenuItemStepMotorSpd[] = 
{
    {(uint8_t *)"Ultra-fast", 0},
    {(uint8_t *)"Fast", 0},
    {(uint8_t *)"Normal", 0},
    {(uint8_t *)"Slow", 0},
    {(uint8_t *)"Ultra-slow", 0},
    {(uint8_t *)"<<<", 0},
};

//WS2812B界面选项对象
static OledMenuItem oledMenuItemWs2812b[] = 
{
    {(uint8_t *)"Mode", 1},
    {(uint8_t *)"Stop color", 1},
    {(uint8_t *)"Cw color", 1},
    {(uint8_t *)"Ccw color", 1},
    {(uint8_t *)"<<<", 0},
};

//WS2812B工作模式界面选项对象
static OledMenuItem oledMenuItemWs2812bWorkMode[] = 
{
    {(uint8_t *)"Follow step", 0},
    {(uint8_t *)"Follow picker", 0},
    {(uint8_t *)"<<<", 0},
};

//WS2812B模式界面选项对象
static OledMenuItem oledMenuItemWs2812bMode[] = 
{
    {(uint8_t *)"Random", 0},
    {(uint8_t *)"Fixed", 1},
    {(uint8_t *)"<<<", 0},
};

//WS2812B固定值界面选项对象
static OledMenuItem oledMenuItemWs2812bFixed[] = 
{
    {(uint8_t *)"Red", 1},
    {(uint8_t *)"Green", 1},
    {(uint8_t *)"Blue", 1},
    {(uint8_t *)"<<<", 0},
};

//设置界面对象
OledMenu oledMenuOption = 
{
    .item             = oledMenuItemOption,
    .itemNum          = sizeof(oledMenuItemOption) / sizeof(oledMenuItemOption[0]),
    .itemIndex        = 0,
    .itemIndexLast    = -1,
    .oledRowIndex     = 0,
    .oledRowIndexLast = -1,
};

//Key界面对象
OledMenu oledMenuKey = 
{
    .item             = oledMenuItemKey,
    .itemNum          = sizeof(oledMenuItemKey) / sizeof(oledMenuItemKey[0]),
    .itemIndex        = 0,
    .itemIndexLast    = -1,
    .oledRowIndex     = 0,
    .oledRowIndexLast = -1,
};

//LED界面对象
OledMenu oledMenuLed = 
{
    .item             = oledMenuItemLed,
    .itemNum          = sizeof(oledMenuItemLed) / sizeof(oledMenuItemLed[0]),
    .itemIndex        = 0,
    .itemIndexLast    = -1,
    .oledRowIndex     = 0,
    .oledRowIndexLast = -1,
};

//LED设置界面对象
OledMenu oledMenuLedOption = 
{
    .item             = oledMenuItemLedOption,
    .itemNum          = sizeof(oledMenuItemLedOption) / sizeof(oledMenuItemLedOption[0]),
    .itemIndex        = 0,
    .itemIndexLast    = -1,
    .oledRowIndex     = 0,
    .oledRowIndexLast = -1,
};

//LED模式界面对象
OledMenu oledMenuLedMode = 
{
    .item             = oledMenuItemLedMode,
    .itemNum          = sizeof(oledMenuItemLedMode) / sizeof(oledMenuItemLedMode[0]),
    .itemIndex        = 0,
    .itemIndexLast    = -1,
    .oledRowIndex     = 0,
    .oledRowIndexLast = -1,
};

//OLED界面对象
OledMenu oledMenuOled = 
{
    .item             = oledMenuItemOled,
    .itemNum          = sizeof(oledMenuItemOled) / sizeof(oledMenuItemOled[0]),
    .itemIndex        = 0,
    .itemIndexLast    = -1,
    .oledRowIndex     = 0,
    .oledRowIndexLast = -1,
};

//OLED方向界面对象
OledMenu oledMenuOledDir = 
{
    .item             = oledMenuItemOledDir,
    .itemNum          = sizeof(oledMenuItemOledDir) / sizeof(oledMenuItemOledDir[0]),
    .itemIndex        = 0,
    .itemIndexLast    = -1,
    .oledRowIndex     = 0,
    .oledRowIndexLast = -1,
};

//OLED亮度界面对象
OledMenu oledMenuOledLight = 
{
    .item             = oledMenuItemOledLight,
    .itemNum          = sizeof(oledMenuItemOledLight) / sizeof(oledMenuItemOledLight[0]),
    .itemIndex        = 0,
    .itemIndexLast    = -1,
    .oledRowIndex     = 0,
    .oledRowIndexLast = -1,
};

//OLED光标风格界面对象
OledMenu oledMenuOledCursorStyle = 
{
    .item             = oledMenuItemOledCursorStyle,
    .itemNum          = sizeof(oledMenuItemOledCursorStyle) / sizeof(oledMenuItemOledCursorStyle[0]),
    .itemIndex        = 0,
    .itemIndexLast    = -1,
    .oledRowIndex     = 0,
    .oledRowIndexLast = -1,
};

//OLED菜单编号界面对象
OledMenu oledMenuOledMenuNumber = 
{
    .item             = oledMenuItemOledMenuNumber,
    .itemNum          = sizeof(oledMenuItemOledMenuNumber) / sizeof(oledMenuItemOledMenuNumber[0]),
    .itemIndex        = 0,
    .itemIndexLast    = -1,
    .oledRowIndex     = 0,
    .oledRowIndexLast = -1,
};

//RS485界面对象
OledMenu oledMenuRs485 = 
{
    .item             = oledMenuItemRs485,
    .itemNum          = sizeof(oledMenuItemRs485) / sizeof(oledMenuItemRs485[0]),
    .itemIndex        = 0,
    .itemIndexLast    = -1,
    .oledRowIndex     = 0,
    .oledRowIndexLast = -1,
};

//RS485模式界面对象
OledMenu oledMenuRs485Mode = 
{
    .item             = oledMenuItemRs485Mode,
    .itemNum          = sizeof(oledMenuItemRs485Mode) / sizeof(oledMenuItemRs485Mode[0]),
    .itemIndex        = 0,
    .itemIndexLast    = -1,
    .oledRowIndex     = 0,
    .oledRowIndexLast = -1,
};

//RS485波特率界面对象
OledMenu oledMenuRs485Baud = 
{
    .item             = oledMenuItemRs485Baud,
    .itemNum          = sizeof(oledMenuItemRs485Baud) / sizeof(oledMenuItemRs485Baud[0]),
    .itemIndex        = 0,
    .itemIndexLast    = -1,
    .oledRowIndex     = 0,
    .oledRowIndexLast = -1,
};

//Step motor界面对象
OledMenu oledMenuStepMotor = 
{
    .item             = oledMenuItemStepMotor,
    .itemNum          = sizeof(oledMenuItemStepMotor) / sizeof(oledMenuItemStepMotor[0]),
    .itemIndex        = 0,
    .itemIndexLast    = -1,
    .oledRowIndex     = 0,
    .oledRowIndexLast = -1,
};

//Step motor模式界面对象
OledMenu oledMenuStepMotorMode = 
{
    .item             = oledMenuItemStepMotorMode,
    .itemNum          = sizeof(oledMenuItemStepMotorMode) / sizeof(oledMenuItemStepMotorMode[0]),
    .itemIndex        = 0,
    .itemIndexLast    = -1,
    .oledRowIndex     = 0,
    .oledRowIndexLast = -1,
};

//Step motor转速界面对象
OledMenu oledMenuStepMotorSpd = 
{
    .item             = oledMenuItemStepMotorSpd,
    .itemNum          = sizeof(oledMenuItemStepMotorSpd) / sizeof(oledMenuItemStepMotorSpd[0]),
    .itemIndex        = 0,
    .itemIndexLast    = -1,
    .oledRowIndex     = 0,
    .oledRowIndexLast = -1,
};

//WS2812B界面对象
OledMenu oledMenuWs2812b = 
{
    .item             = oledMenuItemWs2812b,
    .itemNum          = sizeof(oledMenuItemWs2812b) / sizeof(oledMenuItemWs2812b[0]),
    .itemIndex        = 0,
    .itemIndexLast    = -1,
    .oledRowIndex     = 0,
    .oledRowIndexLast = -1,
};

//WS2812B工作模式界面对象
OledMenu oledMenuWs2812bWorkMode = 
{
    .item             = oledMenuItemWs2812bWorkMode,
    .itemNum          = sizeof(oledMenuItemWs2812bWorkMode) / sizeof(oledMenuItemWs2812bWorkMode[0]),
    .itemIndex        = 0,
    .itemIndexLast    = -1,
    .oledRowIndex     = 0,
    .oledRowIndexLast = -1,
};

//WS2812B模式界面对象
OledMenu oledMenuWs2812bMode = 
{
    .item             = oledMenuItemWs2812bMode,
    .itemNum          = sizeof(oledMenuItemWs2812bMode) / sizeof(oledMenuItemWs2812bMode[0]),
    .itemIndex        = 0,
    .itemIndexLast    = -1,
    .oledRowIndex     = 0,
    .oledRowIndexLast = -1,
};

//WS2812B固定值界面对象
OledMenu oledMenuWs2812bFixed = 
{
    .item             = oledMenuItemWs2812bFixed,
    .itemNum          = sizeof(oledMenuItemWs2812bFixed) / sizeof(oledMenuItemWs2812bFixed[0]),
    .itemIndex        = 0,
    .itemIndexLast    = -1,
    .oledRowIndex     = 0,
    .oledRowIndexLast = -1,
};

uint16_t oledMainPageRefreshInterval;   //OLED主界面刷新时间间隔(ms)

uint8_t oledSelectLevel1;   //OLED一级设置菜单所选编号
uint8_t oledSelectLevel2;   //OLED二级设置菜单所选编号
uint8_t oledSelectLevel3;   //OLED三级设置菜单所选编号
uint8_t oledSelectLevel4;   //OLED四级设置菜单所选编号

uint8_t oledDisModeFlag;    //OLED显示主界面或设置界面标志
uint8_t oledMenuLevel;      //OLED菜单层级

uint8_t oledItemUpDnEnaFlag;    //OLED菜单选项上下移使能标志
uint8_t oledItemUpFlag;         //OLED菜单选项上移标志
uint8_t oledItemDnFlag;         //OLED菜单选项下移标志
uint8_t oledItemSelectFlag;     //OLED菜单选项确认标志

uint8_t oledValSetEnaFlag;  //OLED设置数值使能标志
uint8_t oledValSetSubFlag;  //OLED设置数值减小标志
uint8_t oledValSetPlusFlag; //OLED设置数值增大标志

uint8_t oledOffFlag;        //OLED关闭显示
uint8_t oledDir;            //OLED方向
uint8_t oledLightLevel;     //OLED亮度等级
uint8_t oledCursorStyle;    //OLED光标风格
uint8_t oledMenuNumberFlag; //OLED菜单编号标志
uint8_t oledMenuNumberFlagLast; //OLED菜单编号标志

uint8_t oledWarnOledAwakenedFlag;   //OLED警告OLED已唤醒标志
uint8_t oledWarnKeyLockedFlag;      //OLED警告按键已锁定标志
uint8_t oledWarnKeyUnlockedFlag;    //OLED警告按键已解锁标志

/**
 * @brief   OLED初始化
 * @param   None
 * @retval  None
 * @note    静态函数
*/
static void oled_init(void)
{
    gpio_init_type gpioInitStruct = 
    {
        .gpio_pins           = OLED_SDA_GPIO_PIN,
        .gpio_out_type       = GPIO_OUTPUT_PUSH_PULL,
        .gpio_pull           = GPIO_PULL_NONE,
        .gpio_mode           = GPIO_MODE_OUTPUT,
        .gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER,
    };
    
    //OLED GPIO初始化
    crm_periph_clock_enable(OLED_GPIO_CRM, TRUE);
    gpio_init(OLED_SDA_GPIO_PORT, &gpioInitStruct);
    gpioInitStruct.gpio_pins = OLED_SCL_GPIO_PIN;
    gpio_init(OLED_SCL_GPIO_PORT, &gpioInitStruct);
}


/**
 * @brief   延时
 * @param   t:  时钟周期数量
 * @retval  None
 * @note    静态函数
*/
static void delay(uint32_t t)
{
    while(t--)
    {
        __nop();
    }
}


/**
 * @brief   OLED IIC起始信号
 * @param   None
 * @retval  None
 * @note    静态函数
*/
static void oled_iic_start(void)
{
    OLED_IIC_SCL_HIGH;
    delay(5);
    OLED_IIC_SDA_HIGH;
    delay(5);
    OLED_IIC_SDA_LOW;
    delay(5);
    OLED_IIC_SCL_LOW;
    delay(5);
}


/**
 * @brief   OLED IIC停止信号
 * @param   None
 * @retval  None
 * @note    静态函数
*/
static void oled_iic_stop(void)
{
    OLED_IIC_SCL_HIGH;
    delay(5);
    OLED_IIC_SDA_LOW;
    delay(5);
    OLED_IIC_SDA_HIGH;
    delay(5);
}


/**
 * @brief   OLED IIC等待应答
 * @param   None
 * @retval  None
 * @note    静态函数
*/
static void oled_iic_wait_ack(void)
{
    OLED_IIC_SCL_LOW;
    delay(5);
    OLED_IIC_SCL_HIGH;
    delay(5);
    OLED_IIC_SCL_LOW;
    delay(5);
}


/**
 * @brief   OLED IIC发送一个字节
 * @param   byte:   要发送的数据
 * @retval  None
 * @note    静态函数
*/
static void oled_iic_send_byte(uint8_t byte)
{
    OLED_IIC_SCL_LOW;
    delay(5);
    
    for(uint8_t i = 0; i < 8; i++)
    {
        if(byte << i & 0x80)
        {
            OLED_IIC_SDA_HIGH;
        }
        else
        {
            OLED_IIC_SDA_LOW;
        }
        
        delay(5);
        OLED_IIC_SCL_HIGH;
        delay(5);
        OLED_IIC_SCL_LOW;
        delay(5);
    }
}


/**
 * @brief   OLED IIC发送数据/命令
 * @param   data:           要发送的数据/命令
 * @param   oledSendMode:   发送模式
 * @retval  None
 * @note    None
*/
void oled_iic_send_data(uint8_t data, OledSendMode oledSendMode)
{
    oled_iic_start();
    oled_iic_send_byte(0x78);
    oled_iic_wait_ack();
    if(oledSendMode == OLED_SEND_CMD)
    {
        oled_iic_send_byte(0x00);
    }
    else
    {
        oled_iic_send_byte(0x40);
    }
    oled_iic_wait_ack();
    oled_iic_send_byte(data);
    oled_iic_wait_ack();
    oled_iic_stop();
}


/**
 * @brief   OLED配置
 * @param   None
 * @retval  None
 * @note    None
*/
void oled_config(void)
{
    oled_init();
    
    oledMainPageRefreshInterval = OLED_MAIN_PAGE_REFRESH_INTERVAL;
    
    OLED_IIC_SDA_HIGH;
    OLED_IIC_SCL_HIGH;
}
